/**
 * 
 */
package org.lex.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;

import javax.swing.event.ChangeListener;

/**
 * @author Daniel Liu
 */
public class LineBasedProcess {
	private String[] command = null;
	private StateChangeSupport scs = null;
	private Process process = null;
	private PrintWriter writer = null;
	private ReaderThread readerThread = null;

	/**
	 * @param process
	 */
	public LineBasedProcess(String... command) {
		this.command = command;
		this.scs = new StateChangeSupport();
	}

	public void println(CharSequence cs) {
		writer.print(cs);
		writer.flush();
		writer.println();
	}

	public void start() throws IOException {
		ProcessBuilder pb = new ProcessBuilder(command);
		pb.redirectErrorStream(true);
		this.process = pb.start();
		this.writer = new PrintWriter(process.getOutputStream(), false);
		this.readerThread = new ReaderThread(process.getInputStream(), scs);
		new Thread(this.readerThread).start();
	}

	public void destroy() {
		if (null != process) {
			this.process.destroy();
			this.process = null;
		}
		if (null != readerThread) {
			this.readerThread.stop();
			this.readerThread = null;
		}
	}

	public void addChangeListener(ChangeListener l) {
		scs.addChangeListener(l);
	}

	public ChangeListener[] getChangeListeners() {
		return scs.getChangeListeners();
	}

	public void removeChangeListener(ChangeListener l) {
		scs.removeChangeListener(l);
	}

	// TODO we will use a ExecutorService in the future to replace this
	static class ReaderThread implements Runnable {
		private final StateChangeSupport scs;
		private final BufferedReader reader;
		private boolean stop = false;

		ReaderThread(InputStream in, StateChangeSupport scs) {
			this.reader = new BufferedReader(new InputStreamReader(in));
			this.scs = scs;
		}

		void stop() {
			stop = true;
		}

		public void run() {
			String line = null;
			while (false == stop) {
				try {
					line = reader.readLine();
				} catch (IOException e) {
				}
				if (null == line)
					return;
				else
					scs.fireStateChanged(line);
			}
		}
	}
}
